package com.atguigu.gmall.service.impl;

import com.atguigu.gmall.client.service.ProductFeignClientService;
import com.atguigu.gmall.constant.RedisConst;
import com.atguigu.gmall.entity.CartInfo;
import com.atguigu.gmall.entity.SkuInfo;
import com.atguigu.gmall.mapper.CartInfoMapper;
import com.atguigu.gmall.service.AsyncCartInfoService;
import com.atguigu.gmall.service.CartInfoService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.omg.CORBA.IRObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@Transactional
public class CartInfoServiceImpl extends ServiceImpl<CartInfoMapper,CartInfo> implements CartInfoService {
    //远程调用，根据skuId获取sku信息
    @Autowired
    private ProductFeignClientService productFeignClientService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private AsyncCartInfoService asyncCartInfoService;

    //todo 如果用户未登录，使用的是临时id添加的购物车，他在登录之后怎么合并购物车信息？
    /**/
    //商品已经被加入购物车，数量加1 ，没有则查询出商品信息，加入到购物车
    @Override
    public void saveCart(Long skuId, Integer skuNum, String userId) {
        String cartKey = this.getCartKey(userId); //设置购物车的key
        //查数据库，并进行数据修改操作
        QueryWrapper<CartInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("sku_id", skuId).eq("user_id", userId);
        CartInfo cartInfo = baseMapper.selectOne(queryWrapper);
        if (ObjectUtils.isEmpty(cartInfo)){
            //没有相应的购物车信息，添加到数据库，在添加到redis
            //根据skuId查询商品信息，封装为cartinfo
            cartInfo = this.packageCartInfo(skuId, skuNum, userId);
//            baseMapper.insert(cartInfo);
            asyncCartInfoService.saveCartInfo(cartInfo);//异步操作
        }else {
            //已经存在，修改数量即可，查询价格，修改价格
            BigDecimal price = productFeignClientService.getSkuPriceNow(skuId);
            cartInfo.setRealTimePrice(price);
            cartInfo.setSkuNum(cartInfo.getSkuNum() + skuNum);
//            baseMapper.updateById(cartInfo);//存储到数据库中
            asyncCartInfoService.updateCartInfo(cartInfo);//异步操作
        }
        //查redis,并进行数量修改操作
        BoundHashOperations operations = redisTemplate.boundHashOps(cartKey);
        //获取reids中 该用户的购物车信息
        List<CartInfo> cartInfoList = redisTemplate.boundHashOps(cartKey).values();
        //如果redis中没有数据？
        if (cartInfoList.isEmpty()){
            operations.put(skuId.toString(), cartInfo);//执行新增
        }else {
            for (CartInfo info : cartInfoList) {
                if (info.getSkuId().equals(skuId)){
                    info.setSkuNum(skuNum+info.getSkuNum());  //有相应的数据，那么就修改数量
                    operations.put(skuId.toString(), info);
                    break;//退出循环
                }
            }
            //遍历每条商品信息，检查是否重复添加，是就修改数量
           /* cartInfoList.stream().forEach(redisCartInfo -> {
                if (redisCartInfo.getSkuId().equals(skuId)) {
                    redisCartInfo.setSkuNum(skuNum+redisCartInfo.getSkuNum());  //有相应的数据，那么就修改数量
                    operations.put(skuId.toString(), redisCartInfo);
                    // TODO: 2021/9/7  一旦修改完毕，说明已经可以停止迭代了
                }
            });*/
        }
        this.setCartKeyExpire(cartKey);   //设置购物车过期时间
    }

    @Override
    public List<CartInfo> getCartListByUserId(String userId) {
        //获取购物车的信息
        String cartKey = this.getCartKey(userId);
        //从redis中获取购物车信息
        List<CartInfo> cartInfoList = redisTemplate.boundHashOps(cartKey).values();
        if (CollectionUtils.isEmpty(cartInfoList)){  //如果redis中没有，就查数据库，然后添加到数据
            QueryWrapper<CartInfo> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("user_id", userId);
            cartInfoList = baseMapper.selectList(queryWrapper);
            //再次放到redis中，以及即时更新商品的价格 todo
            this.turnCartInfoToRedis(cartKey,cartInfoList);
        }
        return cartInfoList;
    }

    @Override
    public void deleteCartInfo(String userId, Long skuId) {
        //删除redis
        String cartKey = this.getCartKey(userId);
        BoundHashOperations operations = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = operations.values();
        cartInfoList.stream().forEach(cartInfo -> {
            if (cartInfo.getSkuId().equals(skuId))
                operations.delete(skuId.toString());
        });
        //删除数据库中的记录
        asyncCartInfoService.deleteCartInfo(userId, skuId); //异步删除
    }

    @Override
    public List<CartInfo> getSelectedProduct(String userId) {
        String cartKey = this.getCartKey(userId);
        BoundHashOperations operations = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = operations.values();
        ArrayList<CartInfo> cartInfos = new ArrayList<>();
        cartInfoList.stream().forEach(cartInfo -> {
            if (cartInfo.getIsChecked().equals(1))
                cartInfos.add(cartInfo);
        });
        return cartInfos;
    }

    @Override
    public List<CartInfo> queryFromDbToRedis(String userId) {
        String cartKey = this.getCartKey(userId);
        //根据用户的id获取购物车所有商品信息
        QueryWrapper<CartInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        List<CartInfo> cartInfoList = baseMapper.selectList(queryWrapper);
        if (cartInfoList.isEmpty())
            return null; //没有就返回空值
        //迭代检查商品价格
        cartInfoList.stream().forEach(cartInfo -> {
            BigDecimal skuPriceNow = productFeignClientService.getSkuPriceNow(cartInfo.getSkuId());//检查商品价格
            if (skuPriceNow.compareTo(cartInfo.getCartPrice())!=0){
                cartInfo.setRealTimePrice(skuPriceNow);//不一致，修改
                redisTemplate.boundHashOps(cartKey).put(cartInfo.getSkuId().toString(),cartInfo);
            }
        });
        return cartInfoList;
    }

    /*把数据库数据同步到redis*/
    private void turnCartInfoToRedis(String cartKey, List<CartInfo> cartInfoList) {
        if (CollectionUtils.isEmpty(cartInfoList))
            return;// 数据查询出的数据也为空，直接返回，不会新增
        BoundHashOperations operations = redisTemplate.boundHashOps(cartKey);
        cartInfoList.stream().forEach(cartInfo -> {
            operations.put(cartInfo.getSkuId().toString(), cartInfo);
        });
    }

    //拼接购物车的key
    private String getCartKey(String userId) {
        return RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
    }
    //设置购物车的过期时间
    private void setCartKeyExpire(String cartKey) {
        redisTemplate.expire(cartKey, RedisConst.USER_CART_EXPIRE, TimeUnit.SECONDS);
    }
    private CartInfo packageCartInfo(Long skuId, Integer skuNum, String userId) {
        SkuInfo skuInfo = productFeignClientService.getSkuInfo(skuId);
        CartInfo cartInfo = new CartInfo();
        cartInfo.setUserId(userId);
        cartInfo.setSkuNum(skuNum);
        // 实时价格 =相当于skuInfo.price(); 第一次添加购物车的时候，这个价格就是实时价格。
        cartInfo.setRealTimePrice(skuInfo.getPrice());
        // 默认值1 表示被选中
        cartInfo.setIsChecked(1);
        cartInfo.setImgUrl(skuInfo.getSkuDefaultImg());
        cartInfo.setSkuName(skuInfo.getSkuName());
        cartInfo.setSkuId(skuId);
        // 添加购物车时的价格，默认是最新的价格
        cartInfo.setCartPrice(skuInfo.getPrice());
        return cartInfo;
    }


}
